public class MyLittleClass { private final TimeService timeService; @Inject public MyLittleClass(TimeService timeService) { this.timeService = timeService; } public void printTime() { System.out.println(this.timeService.getTime()); } }
The core Errai IOC module implements the JSR-330 Dependency Injection specification for in-client component wiring.
Dependency injection (DI) allows for cleaner and more modular code, by permitting the implementation of decoupled and type-safe components. By using DI, components do not need to be aware of the implementation of provided services. Instead, they merely declare a contract with the container, which in turn provides instances of the services that component depends on.
Errai only scans the contents of classpath locations (JARs and directories) that have a file called ErraiApp.properties at their root. If dependency injection is not working for you, double-check that you have an ErraiApp.properties in every JAR and directory that contains classes Errai should know about.
A simple example:
public class MyLittleClass { private final TimeService timeService; @Inject public MyLittleClass(TimeService timeService) { this.timeService = timeService; } public void printTime() { System.out.println(this.timeService.getTime()); } }
In this example, we create a simple class which declares a dependency using @Inject for the interface TimeService. In this particular case, we use constructor injection to establish the contract between the container and the component. We can similarly use field injection to the same effect:
public class MyLittleClass { @Inject private TimeService timeService; public void printTime() { System.out.println(this.timeService.getTime()); } }
In order to inject TimeService, you must annotate it with @ApplicationScoped or the Errai DI container will not acknowledge the type as a bean.
@ApplicationScoped public class TimeService { }
Although field injection results in less code, a major disadvantage is that you cannot create immutable classes using the pattern, since the container must first call the default, no argument constructor, and then iterate through its injection tasks, which leaves the potential – albeit remote – that the object could be left in an partially or improperly initialized state. The advantage of constructor injection is that fields can be immutable (final), and invariance rules applied at construction time, leading to earlier failures, and the guarantee of consistent state.